﻿using System.Windows;
using System.Windows.Input;
using System.Windows.Media;

namespace Sidvall.UI.Wpf.Controls
{
    /// <summary>
    ///    Class used to manage generic scoping of access keys
    /// </summary>
    public static class AccessKeyScoper
    {
        /// <summary>
        ///    Identifies the IsAccessKeyScope attached dependency property
        /// </summary>
        public static readonly DependencyProperty IsAccessKeyScopeProperty =
            DependencyProperty.RegisterAttached("IsAccessKeyScope", typeof(bool), typeof(AccessKeyScoper), new PropertyMetadata(false, HandleIsAccessKeyScopePropertyChanged));
        /// <summary>
        ///    Sets the IsAccessKeyScope attached property value for the specified object
        /// </summary>
        /// <param name="obj">The object to retrieve the value for</param>
        /// <param name="value">Whether the object is an access key scope</param>
        public static void SetIsAccessKeyScope(DependencyObject obj, bool value)
        {
            obj.SetValue(AccessKeyScoper.IsAccessKeyScopeProperty, value);
        }
        /// <summary>
        ///    Gets the value of the IsAccessKeyScope attached property for the specified object
        /// </summary>
        /// <param name="obj">The object to retrieve the value for</param>
        /// <returns>The value of IsAccessKeyScope attached property for the specified object</returns>
        public static bool GetIsAccessKeyScope(DependencyObject obj)
        {
            return (bool)obj.GetValue(AccessKeyScoper.IsAccessKeyScopeProperty);
        }
        private static void HandleIsAccessKeyScopePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d == null)
                return;
            if ((bool)e.NewValue)
            {
                AccessKeyManager.RemoveAccessKeyPressedHandler(d, new AccessKeyPressedEventHandler(HandleScopedElementAccessKeyPressed));
                AccessKeyManager.AddAccessKeyPressedHandler(d, new AccessKeyPressedEventHandler(HandleScopedElementAccessKeyPressed));
            }
            else
            {
                AccessKeyManager.RemoveAccessKeyPressedHandler(d, new AccessKeyPressedEventHandler(HandleScopedElementAccessKeyPressed));
            }
        }
        private static void HandleScopedElementAccessKeyPressed(object sender, AccessKeyPressedEventArgs e)
        {
            FrameworkElement focusedElement = Keyboard.FocusedElement as FrameworkElement;
            if (focusedElement == null)
                return; // No focused element.

            if (sender == focusedElement)
                return; // This is the correct target.

            // Look through descendants tree to see if this target is a descendant of
            // the focused element. We will stop looking at either the end of the tree
            // or if a object with multiple children is encountered that this target
            // isn't a descendant of.

            // If no valid target is found, we'll set the scope to the sender which
            // results in skipping to the next target handler in the chain
            // (due to the bug).

            DependencyObject obj = focusedElement as DependencyObject;
            while (obj != null)
            {
                int childCount = VisualTreeHelper.GetChildrenCount(obj);
                for (int i = 0; i < childCount; i++)
                {
                    if (VisualTreeHelper.GetChild(obj, i) == sender)
                        return; // Found correct target; let it execute.
                }

                if (childCount > 1)
                {
                    // This target isn't a direct descendant and there are multiple
                    // direct descendants; skip this target.
                    e.Scope = sender;
                    return;
                }
                else if (childCount == 1)
                {
                    // This target isn't a direct descendant, but we'll keep looking
                    // down the descendants chain to see if it's a descendant of the
                    // direct descendant.
                    obj = VisualTreeHelper.GetChild(obj, 0) as DependencyObject;
                }
                else
                {
                    // End of the line; skip this target.
                    e.Scope = sender;
                    return;
                }
            }
            //if (!Keyboard.IsKeyDown(Key.LeftAlt) && !Keyboard.IsKeyDown(Key.RightAlt) && GetIsAccessKeyScope((DependencyObject)sender))
            //{
            //    e.Scope = sender;
            //    e.Handled = true;
            //}
        }
    }
}
